﻿using System;
using System.Diagnostics;
using System.Text;
using System.Windows.Controls;
using System.Windows.Input;
using MVVMFoundation;
using TextCompare;

namespace DictationTool.ViewModel
{
    class DictationViewModel : ObservableObject
    {
        #region Constructor

        public DictationViewModel()
        {
            Saved = true;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Get the value whether dictation has been save.
        /// </summary>
        public bool Saved { get; private set; }

        /// <summary>
        /// The dictation Text
        /// </summary>
        public string DictationText
        {
            get { return dictationText; }
            set
            {
                dictationText = value;
                Saved = false;
                base.RaisePropertyChanged("DictationText");
            }
        }

        /// <summary>
        /// The original text
        /// </summary>
        public string OriginalText
        {
            get { return originalText; }
            set
            {
                originalText = value;
                Saved = false;
                base.RaisePropertyChanged("OriginalText");
            }
        }

        /// <summary>
        /// The compared result
        /// </summary>
        public RichTextBox ComparedText
        {
            get { return comparedText; }
            set
            {
                comparedText = value;
                Saved = false;
                base.RaisePropertyChanged("ComparedText");
            }
        }

        /// <summary>
        /// The correct percent
        /// </summary>
        public string CorrectPercent
        {
            get { return correctPercent; }
            set
            {
                correctPercent = value;
                base.RaisePropertyChanged("CorrectPercent");
            }
        }

        /// <summary>
        /// the consuming time of compare
        /// </summary>
        public string TotalTime
        {
            get { return totalTime; }
            set
            {
                totalTime = value;
                base.RaisePropertyChanged("TotalTime");
            }
        }

        /// <summary>
        /// The command to compare by char
        /// </summary>
        public ICommand CompareCharCommand
        {
            get
            {
                return new RelayCommand(() => { Compare(CompareOption.Char); });
            }
        }

        /// <summary>
        /// The command to compare by string
        /// </summary>
        public ICommand CompareStringCommand
        {
            get
            {
                return new RelayCommand(() => { Compare(CompareOption.String); });
            }
        }

        public bool IsCompared
        {
            get { return isCompared; }
            set
            {
                isCompared = value;
                base.RaisePropertyChanged("IsCompared");
            }
        }

        public bool Select
        {
            get { return select; }
            set
            {
                select = value;
                base.RaisePropertyChanged("Select");
            }
        }
        
        #endregion

        #region Methods

        public SaveResult GetSaveResult()
        {
            Saved = true;
            return new SaveResult(OriginalText, DictationText, result);
        }

        public void SetResult(SaveResult saveResult)
        {
            if (saveResult != null)
            {
                OriginalText = saveResult.OrignalText;
                DictationText = saveResult.DictationText;
                result = saveResult.Compared;
                FormatCompareText(result);
                CorrectPercent = (result == null) ? string.Empty : string.Format("{0}%", result.CorrectPercent);
            }
            Saved = true;
        }

        public string SaveToHtml(string title)
        {
            HtmlBuilder htmlBuilder = new HtmlBuilder(title);
            htmlBuilder.Append("Original", OriginalText);

            HtmlFormatter html = new HtmlFormatter();
            html.Write(compareController.TextMatcher(OriginalText, DictationText, result.CompareOption), result.MatchPoints);
            htmlBuilder.Append("Dictation", html.HtmlContent);

            return htmlBuilder.HtmlContent;
        }

        private void Compare(CompareOption compareOption)
        {
            if (string.IsNullOrWhiteSpace(OriginalText) || string.IsNullOrWhiteSpace(DictationText))
                return;

            Stopwatch sw;
            sw = Stopwatch.StartNew();

            result = compareController.Compare(OriginalText, DictationText, compareOption);
            FormatCompareText(result);

            TotalTime = sw.Elapsed.ToString();
            CorrectPercent = string.Format("{0}%", result.CorrectPercent);

            IsCompared = true;
        }

        private void FormatCompareText(CompareResult result)
        {
            if (result != null)
            {
                ComparedText = new RichTextBox();
                TextBlockFormatter formatter = new TextBlockFormatter(ComparedText);
                formatter.Write(compareController.TextMatcher(OriginalText, DictationText, result.CompareOption), result.MatchPoints);
            }
            else
            {
                ComparedText = null;
            }
        }

        private CompareOption GetLanugage()
        {
            Encoding utf = Encoding.UTF8;
            string text = OriginalText.Substring(0, 1);
            byte[] utfbytes = utf.GetBytes(text);

            return (text.Length == utfbytes.Length) ? CompareOption.String : CompareOption.Char;
        }

        #endregion

        #region Fields

        private bool select = true;
        private bool isCompared;
        private string dictationText;
        private string originalText;
        private string correctPercent;
        private string totalTime;
        private RichTextBox comparedText;
        private CompareResult result;
        private CompareControl compareController = new CompareControl();

        #endregion
    }

    [Serializable]
    sealed class SaveResult
    {
        public SaveResult(string orignal, string dictation, CompareResult compared)
        {
            this.OrignalText = orignal;
            this.DictationText = dictation;
            this.Compared = compared;
        }

        public string OrignalText { get; set; }
        public string DictationText { get; set; }
        public CompareResult Compared { get; set; }
    }
}
